<?php

namespace addons\litestore\model;

use app\admin\model\OrderSfLog;
use app\common\model\User;
use Exception;
use think\Model;
use think\Db;

class Litestoreorder extends Model
{
    // 表名
    protected $name = 'litestore_order';

    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';

    // 追加属性
    // protected $append = [
    //     'pay_status_text',
    //     'pay_time_text',
    //     'freight_status_text',
    //     'freight_time_text',
    //     'receipt_status_text',
    //     'receipt_time_text',
    //     'order_status_text',
    //     'creattime_text',
    // ];

    public function getCreatetimeAttr($value, $data)
    {
        return datetime($data['createtime']);
    }

    public function getUpdatetimeAttr($value, $data)
    {
        return datetime($data['createtime']);
    }


    public function cancel($user_id, $order_id)
    {
        if ($this['pay_status'] === '20') {
            $this->setError('已付款订单不可取消');
            return false;
        }
        $goods = $this['goods'];
        $this->backGoodsStock($goods);

        $order = self::get([
            'id' => $order_id,
            'user_id' => $user_id,
            'order_status' => ['<>', '20']
        ]);

        if($order->vip_use_num){
            $vip_log_model = new \app\admin\model\VipLog;
            $vip_log = $vip_log_model->where('id',$order->vip_log_id)->find();
            $vip_log->used_service_number += $order->vip_use_num;
            $vip_log->save();
        }

        return $order->save([
            'order_status' => '20'
        ]);
    }
    private function backGoodsStock(&$goodsList)
    {
        $goodsSpecSave = [];
        foreach ($goodsList as $goods) {
            // 下单减库存
            if ($goods['deduct_stock_type'] === '10') {
                $goodsSpecSave[] = [
                    'goods_spec_id' => $goods['goods_spec_id'],
                    'stock_num' => ['inc', $goods['total_num']]
                ];
            }
        }
        if (!empty($goodsSpecSave)) {
            // 更新商品规格库存
            return (new Litestoregoodsspec)->isUpdate()->saveAll($goodsSpecSave);
        }
        return true;
    }

    // 师傅确认订单收货
    public function finish($sf_id, $order_id,$code)
    {
        if (!$order = self::get([
            'id' => $order_id,
            'order_status' => ['<>', '20']
        ])) {
            $this->setError('订单不存在');
            return false;
        }
        
        if ($order['freight_status'] === '10' || $order['receipt_status'] === '20') {
            $this->setError('该订单不合法');
            return false;
        }

        if($order['sf_id'] != $sf_id){
            $this->setError('该订单和你身份不符合，请核实该订单');
            return false;
        }
        if($order['code'] != $code){
            $this->setError('你输入的识别码有误，请核对后确认收货');
            return false;
        }

        if($order['work_status'] == '10'){
            $this->setError('未开始工作不能确认完成');
            return false;
        }


        Db::startTrans();
        // 师傅收益
        $sf_order_ratio = config('site.sf_order_ratio');
        if($sf_order_ratio){
            $money = bcmul($order['pay_price'], ($sf_order_ratio /  100),2);
            User::money($money,$order['sf_id'],'订单收益',$order['id']);
        }
        $order->save([
            'receipt_status' => '20',
            'receipt_time' => time(),
            'order_status' => '30'
        ]);
        Db::commit();
        return true;
    }

    // 师傅确认开始工作
    public function work($sf_id, $order_id)
    {
        if (!$order = self::get([
            'id' => $order_id,
            'order_status' => ['<>', '20']
        ])) {
            $this->setError('订单不存在');
            return false;
        }
        
        if ($order['freight_status'] === '10' || $order['receipt_status'] === '20') {
            $this->setError('该订单不合法');
            return false;
        }

        if($order['work_status'] == '20'){
            $this->setError('你已经开始工作，请勿重复点击');
            return false;
        }

        if($order['sf_id'] != $sf_id){
            $this->setError('该订单和你身份不符合，请核实该订单');
            return false;
        }

        Db::startTrans();
        $order->save([
            'work_status' => '20',
            'work_time' => time(),
        ]);
        Db::commit();
        return true;
    }


    public function checkGoodsStatusFromOrder($goodsList)
    {
        foreach ($goodsList as $goods) {
            //商品是否下架
            if ($goods['goods']['goods_status'] !== '10') {
                $this->setError('很抱歉，商品 [' . $goods['goods_name'] . '] 已下架');
                return false;
            }
            //付款减库存
            if ($goods['deduct_stock_type'] === '20' && $goods['spec']['stock_num'] < 1) {
                $this->setError('很抱歉，商品 [' . $goods['goods_name'] . '] 库存不足');
                return false;
            }
        }
        return true;
    }

    public function getList($user_id, $type = null, $page = null)
    {
        $order = $this->with(['goods'])
            ->where('user_id', '=', $user_id)
            ->where('order_status', '<>', '20')
            ->order(['createtime' => 'desc']);

        // 未付款
        if ($type == 1) {
            $order->where('pay_status', 10);
        } elseif ($type > 1) {
            // 已付款
            $order->where('pay_status', 20);
            // 已完成
            if ($type == 4) {
                $order->where('order_status', 30);
            } else {
                $order->where('order_status', 10);
                // 待受理
                if ($type == 2) {
                    $order->where('freight_status', 10);
                    // 已接单
                } elseif ($type == 3) {
                    $order->where('work_status', 10);
                    $order->where('freight_status', 20);
                }elseif($type == 5){
                    $order->where('freight_status', 20);
                    $order->where('work_status', 20);
                }
            }
        }

        if ($page) {
            $order->limit(($page - 1) * 10, 10);
        } else {
            $order->limit(50);
        }

        $order = $order->select();
        foreach ($order as $v) {
            foreach ($v['goods'] as $index => $item) {
                $item['image'] = cdnurl(explode(",", $item['images'])[0], true);
            }
        }

        return $order;
    }

    public function getOrderDetail($order_id, $user_id)
    {
        if (!$order = self::get([
            'order_id' => $order_id,
            // 'litestoreorder.user_id' => $user_id,
            'order_status' => ['<>', '20']
        ], ['goods' => ['spec'], 'address'])) {
            return $this->setError('订单不存在');
            return false;
        }
        $goodsList = [];
        foreach ($order['goods'] as $index => $item) {
            $item['image'] = cdnurl(explode(",", $item['images'])[0], true);
            $item['sku_image'] = $item['spec']['spec_image'] == '' ? '' : cdnurl($item['spec']['spec_image'], true);
            $goodsList[] = $item;
        }
        $order['goods'] = $goodsList;
        return $order;
    }

    public function payDetail($order_no)
    {
        return self::get(['order_no' => $order_no, 'pay_status' => 10], ['goods']);
    }

    public function getCart($user_id)
    {
        $model = new CacheCart($user_id);
        return $model->getList($user_id);
    }

    public function CarclearAll($user_id)
    {
        $Card = new CacheCart($user_id);
        $Card->clearAll();
    }

    public function getBuyNow($user_id, $goods_id, $goods_num, $goods_sku_id)
    {
        // 商品信息
        $goods = Wxlitestoregoods::detail($goods_id);
        $goods['show_error'] = 0;
        // 判断商品是否下架
        if ($goods['goods_status'] !== '10') {
            $goods['show_error'] = 1;
            $goods['show_error_text'] = '已下架';
            $this->setError('很抱歉，商品信息不存在或已下架');
        }
        // 商品sku信息
        $goods['goods_sku'] = $goods->getGoodsSku($goods_sku_id);
        // 判断商品库存
        if ($goods_num > $goods['goods_sku']['stock_num']) {
            $goods['show_error'] = 2;
            $goods['show_error_text'] = '库存不足';
            $this->setError('很抱歉，商品库存不足');
        }
        // 商品单价
        $goods['goods_price'] = $goods['goods_sku']['goods_price'];
        // 商品总价
        $goods['total_num'] = $goods_num;
        $goods['total_price'] = $totalPrice = bcmul($goods['goods_price'], $goods_num, 2);
        // 商品总重量
        $goods_total_weight = bcmul($goods['goods_sku']['goods_weight'], $goods_num, 2);
        // 当前用户收货城市id
        $defaultcity = Litestoreadress::getdefault($user_id);
        $cityId = $defaultcity ? $defaultcity['city_id'] : null;
        // 是否存在收货地址
        $exist_address = $defaultcity;
        // 验证用户收货地址是否存在运费规则中
        // if (!$intraRegion = $goods['freight']->checkAddress($cityId)) {
        //     $exist_address && $this->setError('很抱歉，您的收货地址不在配送范围内');
        // }
        // 计算配送费用
        // $expressPrice = $intraRegion ?
        // $goods['freight']->calcTotalFee($goods_num, $goods_total_weight, $cityId) : 0;
        $expressPrice = 0;

        // 会员卡
        $vip_log = db('vip_log')->where(['user_id' => $user_id])->where('end_time','>',time())->find();
        $vip_price = 0;
        if($vip_log){
            // 判断免费服务是否存在
            if($vip_log['grati_category_ids']){

                if(in_array($goods['category_id'],explode(',', $vip_log['grati_category_ids']))){
                    $vip_price = $totalPrice;
                }else{
                    if($goods['category_id'] == $vip_log['service_category_id']){
                        // 判断服务是否还有次数
                        if($vip_log['used_service_number'] > 0){
                            if($vip_log['used_service_number'] >= $goods_num){
                                $vip_price = $totalPrice;
                            }else{
                                $vip_price = bcmul($goods['goods_price'], $vip_log['used_service_number'], 2);
                            }
                        }
                    }
                }
            // 判断是否有服务
            }elseif($goods['category_id'] == $vip_log['service_category_id']){
                // 判断服务是否还有次数
                if($vip_log['used_service_number'] > 0){
                    if($vip_log['used_service_number'] >= $goods_num){
                        $vip_price = $totalPrice;
                    }else{
                        $vip_price = bcmul($goods['goods_price'], $vip_log['used_service_number'], 2);
                    }
                }
            }
        }

        

        return [
            'goods_list' => [$goods],               // 商品详情
            'order_total_num' => $goods_num,        // 商品总数量
            'order_total_price' => $totalPrice,    // 商品总金额 (不含运费)
            'order_pay_price' => bcsub(bcadd($totalPrice, $expressPrice, 2),$vip_price),  // 实际支付金额
            'address' => $defaultcity,  // 默认地址
            // 'exist_address' => $exist_address,  // 是否存在收货地址
            // 'express_price' => $expressPrice,    // 配送费用
            // 'intra_region' => $intraRegion,    // 当前用户收货城市是否存在配送规则中
            'has_error' => $this->hasError(),
            'error_msg' => $this->getError() ?? '',
        ];
    }

    public function order_add($user_id, $order,$coupon_id = '')
    {
        if (empty($order['address'])) {
            $this->setError('请先选择收货地址');
            return false;
        }

        $order['coupon_money'] = 0;
        if($order['order_pay_price'] == $order['order_total_price']){
            if($coupon_id){
                $coupon = db('coupon_history')->alias('a')->field('a.id,a.coupon_id,b.goods_type,b.goods_value,b.name,b.discount,b.min')
                ->join('coupon b','a.coupon_id = b.id')->where('a.coupon_id',$coupon_id)->where('a.use_status',0)->find();
                if($coupon){
                    foreach($order['goods_list'] as $v){
                        if($coupon['min'] <= $order['order_pay_price']){
                            if($coupon['goods_type'] == 0){
                                $order['order_pay_price'] = bcsub($order['order_pay_price'],$coupon['discount'],2);
                                $order['coupon_money'] = $coupon['discount'];
                            }elseif($coupon['goods_type'] == 1){
                               
                                if(in_array($v['category_id'],explode(',',$coupon['goods_value']))){
                                    $order['order_pay_price'] = bcsub($order['order_pay_price'],$coupon['discount'],2);
                                    $order['coupon_money'] = $coupon['discount'];
                                }
                            }elseif($coupon['goods_type'] == 2){
                                if(in_array($v['goods_id'],explode(',',$coupon['goods_value']))){
                                    $order['order_pay_price'] = bcsub($order['order_pay_price'],$coupon['discount'],2);
                                    
                                    $order['coupon_money'] = $coupon['discount'];
                                }
                            }
                        }
                    }
    
                    if(!$coupon['discount']){
                        $this->setError('无效的优惠券');
                        return false;
                    }
                }
                
            }
        }

        $vip_log_model = new \app\admin\model\VipLog;
        // 会员卡
        $vip_log = $vip_log_model->where(['user_id' => $user_id])->where('end_time','>',time())->find();
        $vip_price = 0;
        $used_service_number = 0;
        if($vip_log){

            foreach($order['goods_list'] as $v){
                 // 判断免费服务是否存在
                if($vip_log['grati_category_ids']){
                    if(in_array($v['category_id'],explode(',', $vip_log['grati_category_ids']))){
                        $order['order_pay_price'] = 0;
                    }else{
                        if($v['category_id'] == $vip_log['service_category_id']){
                            // 判断服务是否还有次数
                            if($vip_log['used_service_number'] > 0){
                                if($vip_log['used_service_number'] >= $v['total_num']){
                                    $order['order_pay_price'] = 0;
                                    $used_service_number = $v['total_num'];
                                }else{
                                    $order['order_pay_price'] = bcsub($order['order_pay_price'],bcmul($v['goods_price'], $vip_log['used_service_number'], 2),2);
                                    $used_service_number = $vip_log['used_service_number'];
                                }
                            }
                        }
                    }
                // 判断是否有服务
                }elseif($v['category_id'] == $vip_log['service_category_id']){
                    // 判断服务是否还有次数
                    if($vip_log['used_service_number'] > 0){
                        if($vip_log['used_service_number'] >= $v['total_num']){
                            $order['order_pay_price'] = 0;
                            $used_service_number = $v['total_num'];
                        }else{
                            $order['order_pay_price'] = bcsub($order['order_pay_price'],bcmul($v['goods_price'], $vip_log['used_service_number'], 2),2);
                            $used_service_number = $vip_log['used_service_number'];
                        }
                    }
                }
                  
            }
           
        }

        
        

        if($order['order_pay_price'] < 0){
            $order['order_pay_price'] = '0.01';
        }

        Db::startTrans();

        

        $order_no = $this->orderNo();
        if($order['coupon_money']){
            $this->couponHistory()->where('id',$coupon['id'])->update(['use_status' => 1,'use_time' => time(),'order_sn' => $order_no]);
        }else{
            
        }
        
        $toreorder_data = [
            'user_id' => $user_id,
            'order_no' => $order_no,
            'total_price' => $order['order_total_price'],
            'pay_price' => $order['order_pay_price'],
            'appointment_time' => $order['appointment_time'],
            'coupon_money' => $order['coupon_money'],
            // 'express_price' => $order['express_price'],
            'code' => mt_rand(1000, 9999),
            'express_price' => 0,
        ];
        
        
        // 更新会员卡
        if($used_service_number){
            $vip_log->used_service_number -= $used_service_number;
            $vip_log->save();
            $toreorder_data['vip_use_num'] = $used_service_number;
            $toreorder_data['vip_log_id'] =  $vip_log->id;
        }
        
        
        // 记录订单信息
        $this->save($toreorder_data);
        
        
        // 订单商品列表
        $goodsList = [];
        // 更新商品库存 (下单减库存)
        $deductStockData = [];
        foreach ($order['goods_list'] as $goods) {
            /* @var Goods $goods */
            $goodsList[] = [
                'user_id' => $user_id,
                'goods_id' => $goods['goods_id'],
                'goods_name' => $goods['goods_name'],
                'images' => $goods['images'],
                'deduct_stock_type' => $goods['deduct_stock_type'],
                'spec_type' => $goods['spec_type'],
                'spec_sku_id' => $goods['goods_sku']['spec_sku_id'],
                'goods_spec_id' => $goods['goods_sku']['goods_spec_id'],
                'goods_attr' => $goods['goods_sku']['goods_attr'],
                'content' => $goods['content'],
                'goods_no' => $goods['goods_sku']['goods_no'],
                'goods_price' => $goods['goods_sku']['goods_price'],
                'line_price' => $goods['goods_sku']['line_price'],
                'goods_weight' => $goods['goods_sku']['goods_weight'],
                'total_num' => $goods['total_num'],
                'total_price' => $goods['total_price'],
            ];
            // 下单减库存
            $goods['deduct_stock_type'] === '10' && $deductStockData[] = [
                'goods_spec_id' => $goods['goods_sku']['goods_spec_id'],
                'stock_num' => ['dec', $goods['total_num']]
            ];
        }
        // 保存订单商品信息
        $this->goods()->saveAll($goodsList);
        // 更新商品库存
        !empty($deductStockData) && (new Litestoregoodsspec)->isUpdate()->saveAll($deductStockData);
        // 记录收货地址
        $this->address()->save([
            'user_id' => $user_id,
            'name' => $order['address']['name'],
            'phone' => $order['address']['phone'],
            'province_id' => $order['address']['province_id'],
            'city_id' => $order['address']['city_id'],
            'region_id' => $order['address']['region_id'],
            'detail' => $order['address']['detail'],
            'lng' => $order['address']['lng'],
            'lat' => $order['address']['lat'],
            'addres' => $order['address']['addres'],
        ]);

        
        Db::commit();
        return true;
    }

    public function getPayStatusList()
    {
        return ['10' => __('Pay_status 10'), '20' => __('Pay_status 20')];
    }

    public function getFreightStatusList()
    {
        return ['10' => __('Freight_status 10'), '20' => __('Freight_status 20')];
    }

    public function getReceiptStatusList()
    {
        return ['10' => __('Receipt_status 10'), '20' => __('Receipt_status 20')];
    }

    public function getOrderStatusList()
    {
        return ['10' => __('Order_status 10'), '20' => __('Order_status 20'), '30' => __('Order_status 30')];
    }


    public function getPayStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pay_status']) ? $data['pay_status'] : '');
        $list = $this->getPayStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getPayTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['pay_time']) ? $data['pay_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getFreightStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['freight_status']) ? $data['freight_status'] : '');
        $list = $this->getFreightStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getFreightTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['freight_time']) ? $data['freight_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getReceiptStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['receipt_status']) ? $data['receipt_status'] : '');
        $list = $this->getReceiptStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }


    public function getReceiptTimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['receipt_time']) ? $data['receipt_time'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getOrderStatusTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['order_status']) ? $data['order_status'] : '');
        $list = $this->getOrderStatusList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getCreattimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['createtime']) ? $data['createtime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;;
    }

    protected function setPayTimeAttr($value)
    {
        return $value && !is_numeric($value) ? strtotime($value) : $value;
    }

    protected function setFreightTimeAttr($value)
    {
        return $value && !is_numeric($value) ? strtotime($value) : $value;
    }

    protected function setReceiptTimeAttr($value)
    {
        return $value && !is_numeric($value) ? strtotime($value) : $value;
    }

    public function goods()
    {
        return $this->hasMany('Litestoreordergoods', 'order_id', 'id');
    }

    public function address()
    {
        return $this->hasOne('Litestoreorderaddress', 'order_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }

    public function couponHistory()
    {
        return $this->hasOne('\\app\\common\\model\\CouponHistory', 'order_id', 'id', [], 'LEFT')->setEagerlyType(0);
    }

    private function setError($error)
    {
        empty($this->error) && $this->error = $error;
    }

    protected function orderNo()
    {
        return date('Ymd') . substr(implode(NULL, array_map('ord', str_split(substr(uniqid(), 7, 13), 1))), 0, 8);
    }

    public function hasError()
    {
        return !empty($this->error);
    }

    public function updatePayStatus($transaction_id)
    {
        Db::startTrans();
        // 更新商品库存、销量
        $GoodsModel = new Wxlitestoregoods;
        $GoodsModel->updateStockSales($this['goods']);
        // 更新订单状态
        $this->save([
            'pay_status' => '20',
            'pay_time' => time(),
            'transaction_id' => $transaction_id,
        ]);
        Db::commit();
        return true;
    }

    // 预约时间
    public function appointmentTime($time_type,$time_hour)
    {   
        if($time_type == 1){
            $time_hour = strtotime("{$time_hour}");
            // if($time_hour < time()){
            //     $this->error = '该时间段已预约满，请换个时间预约';
            //     return false;
            // }
        }elseif($time_type == 2){
            $time_hour = strtotime("+1 day {$time_hour}");
            // if($time_hour < time()){
            //     $this->error = '该时间段已预约满，请换个时间预约';
            //     return false;
            // }
        }else{
            $this->setError('参数不正确');
            return false;
        }

        return $time_hour;
        

    }

    // 师傅订单列表
    public function getListSf($user_id, $type = null, $page = null)
    {
        $order = $this->with(['goods'])
            ->where('sf_id', '=', $user_id)
            ->where('order_status', '<>', '20')
            ->where('freight_status', '20')
            ->order(['createtime' => 'desc']);

        // 进行中
        if ($type == 1) {
            $order->where('order_status', 10);
        } elseif ($type == 2) {
            // 完成
            $order->where('order_status', 30);
           
        }

        $order->limit(($page - 1) * 10, 10);
       

        $order = $order->select();
        foreach ($order as $v) {
            foreach ($v['goods'] as $index => $item) {
                $item['image'] = cdnurl(explode(",", $item['images'])[0], true);
            }
        }

        return $order;
    }

    // 师傅取消接单任务
    public function sfCancel($sf_id, $order_id,$describe)
    {
        if(!$describe){
            $this->setError('请输入取消理由');

            return false;
        }
        $order = self::get([
            'id' => $order_id,
            'sf_id' => $sf_id,
            'freight_status' => '20',
            'order_status' => '10',
        ]);
        if(!$order){
            $this->setError('请勿重复操作');

            return false;
        }

        $sf = db('user_id_card')->field(true)->where('user_id',$sf_id)->find();
        $data['order_id'] = $order['id'];
        $data['sf_id'] = $sf['user_id'];
        $data['name'] = $sf['name'];
        $data['mobile'] = $sf['mobile'];
        $data['status'] = '20';
        $data['describe'] = $describe;


        Db::startTrans();
        $ret1 = db('user')->where('id',$sf_id)->setInc('order_taking_cancel');
        $ret2 = (new OrderSfLog())->save($data);
        $ret3 = $order->save([
            'freight_status' => '10',
            'sf_id' => ''
        ]);

        if(!$ret1 && !$ret2 && !$ret3){
            $this->setError('取消失败,请重新操作');
            return false;
        }
        Db::commit();
        return true;
        
    }
  
}
